﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace MyMedia.Libraries
{
    public class USBDetect : Form
    {
        private Container components = null;

        public event DeviceDismountedHandler DeviceDismounted;

        public event iPodConnectedHandler iPodConnected;

        public event iPodDisconnectedHandler iPodDisconnected;

        public event iPodMountedHandler iPodMounted;

        public USBDetect()
        {
            this.InitializeComponent();
            this.RegisterHidNotification();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && (this.components != null))
            {
                this.components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void InitializeComponent()
        {
            this.components = new Container();
            this.Text = "USBDetect";
        }

        private void OnDeviceChange(ref Message msg)
        {
            int num = msg.WParam.ToInt32();
            Debug.WriteLine("wParam=" + num.ToString());
            if (num == 0x8000)
            {
                Win32.DEV_BROADCAST_HDR structure = new Win32.DEV_BROADCAST_HDR();
                Win32.DEV_BROADCAST_DEVICEINTERFACE1 dev_broadcast_deviceinterface = new Win32.DEV_BROADCAST_DEVICEINTERFACE1();
                Win32.DEV_BROADCAST_VOLUME dev_broadcast_volume = new Win32.DEV_BROADCAST_VOLUME();
                Marshal.PtrToStructure(msg.LParam, structure);
                switch (structure.dbcc_devicetype)
                {
                    case 2:
                        {
                            Marshal.PtrToStructure(msg.LParam, dev_broadcast_volume);
                            Debug.WriteLine(dev_broadcast_volume.dbcv_unitmask.ToString());
                            string iPodDriveLetter = Convert.ToChar((int)(Convert.ToInt32(Math.Log((double)dev_broadcast_volume.dbcv_unitmask, 2.0)) + 0x41)).ToString();
                            if (File.Exists(iPodDriveLetter + @":\iPod_Control\iTunes\iTunesDB"))
                            {
                                this.iPodMounted(this, new EventArgs(), iPodDriveLetter);
                            }
                            return;
                        }
                    case 5:
                        {
                            Marshal.PtrToStructure(msg.LParam, dev_broadcast_deviceinterface);
                            Guid guid = new Guid(dev_broadcast_deviceinterface.dbcc_classguid);
                            if (guid == Win32.GUID_IPOD_3G)
                            {
                                this.iPodConnected(this, new EventArgs());
                            }
                            break;
                        }
                }
            }
            else if (num == 0x8004)
            {
                Win32.DEV_BROADCAST_HDR dev_broadcast_hdr2 = new Win32.DEV_BROADCAST_HDR();
                Win32.DEV_BROADCAST_DEVICEINTERFACE1 dev_broadcast_deviceinterface2 = new Win32.DEV_BROADCAST_DEVICEINTERFACE1();
                Win32.DEV_BROADCAST_VOLUME dev_broadcast_volume2 = new Win32.DEV_BROADCAST_VOLUME();
                Marshal.PtrToStructure(msg.LParam, dev_broadcast_hdr2);
                switch (dev_broadcast_hdr2.dbcc_devicetype)
                {
                    case 2:
                        {
                            Marshal.PtrToStructure(msg.LParam, dev_broadcast_volume2);
                            Debug.WriteLine(dev_broadcast_volume2.dbcv_unitmask.ToString());
                            int num3 = (int)Math.Log((double)dev_broadcast_volume2.dbcv_unitmask, 2.0);
                            string deviceDriveLetter = Convert.ToChar((int)(num3 + 0x41)).ToString();
                            this.DeviceDismounted(this, new EventArgs(), deviceDriveLetter);
                            break;
                        }
                    case 5:
                        {
                            Marshal.PtrToStructure(msg.LParam, dev_broadcast_deviceinterface2);
                            Guid guid2 = new Guid(dev_broadcast_deviceinterface2.dbcc_classguid);
                            if (guid2 == Win32.GUID_IPOD_3G)
                            {
                                this.iPodDisconnected(this, new EventArgs());
                            }
                            break;
                        }
                }
            }
        }

        public void RegisterHidNotification()
        {
            Win32.DEV_BROADCAST_DEVICEINTERFACE structure = new Win32.DEV_BROADCAST_DEVICEINTERFACE();
            int cb = Marshal.SizeOf(structure);
            structure.dbcc_size = cb;
            structure.dbcc_devicetype = 5;
            structure.dbcc_reserved = 0;
            structure.dbcc_classguid = Win32.GUID_IO_MEDIA_ARRIVAL;
            IntPtr ptr = Marshal.AllocHGlobal(cb);
            Marshal.StructureToPtr(structure, ptr, true);
            IntPtr ptr2 = Win32.RegisterDeviceNotification(base.Handle, ptr, 0);
            Marshal.PtrToStructure(ptr, structure);
            if (ptr2.ToInt32() == IntPtr.Zero.ToInt32())
            {
                MessageBox.Show(Win32.GetLastError().ToString());
            }
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == 0x219)
            {
                this.OnDeviceChange(ref m);
            }
            base.WndProc(ref m);
        }

        private void writeLog(string Msg)
        {
            StreamWriter writer = File.AppendText(@"C:\detect.log");
            writer.WriteLine(Msg);
            writer.Close();
        }

        public class Win32
        {
            public const int DBT_DEVICEARRIVAL = 0x8000;
            public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
            public const int DBT_DEVTYP_DEVICEINTERFACE = 5;
            public const int DBT_DEVTYP_VOLUME = 2;
            public const int DEVICE_NOTIFY_SERVICE_HANDLE = 1;
            public const int DEVICE_NOTIFY_WINDOW_HANDLE = 0;
            public static Guid GUID_IO_MEDIA_ARRIVAL = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
            public static Guid GUID_IPOD_3G = new Guid("a5dcbf10-6530-11d2-901f-00c04fb951ed");
            public const int WM_DEVICECHANGE = 0x219;

            [DllImport("kernel32.dll")]
            public static extern int GetLastError();
            [DllImport("user32.dll", SetLastError = true)]
            public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, int Flags);

            [StructLayout(LayoutKind.Sequential)]
            public class DEV_BROADCAST_DEVICEINTERFACE
            {
                public int dbcc_size;
                public int dbcc_devicetype;
                public int dbcc_reserved;
                public Guid dbcc_classguid;
                public short dbcc_name;
            }

            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public class DEV_BROADCAST_DEVICEINTERFACE1
            {
                public int dbcc_size;
                public int dbcc_devicetype;
                public int dbcc_reserved;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x10, ArraySubType = UnmanagedType.U1)]
                public byte[] dbcc_classguid;
                [MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x80)]
                public char[] dbcc_name;
            }

            [StructLayout(LayoutKind.Sequential)]
            public class DEV_BROADCAST_HDR
            {
                public int dbcc_size;
                public int dbcc_devicetype;
                public int dbcc_reserved;
            }

            [StructLayout(LayoutKind.Sequential)]
            public class DEV_BROADCAST_VOLUME
            {
                public int dbcv_size;
                public int dbcv_devicetype;
                public int dbcv_reserved;
                public int dbcv_unitmask;
                public ushort dbcv_flags;
            }
        }
    }
}

